const dgram = require('dgram');

const { on_set_rfid_judgment } = require('./utils/set-rfid.cjs')

// 心跳时长
const heartbeatInterval = 1000;

const connectUdp = (config) => {
  const client = dgram.createSocket('udp4');

  const onContentClient = () => {
    client.bind(() => {
      console.log("UDP client bound");

      // 开始发送心跳
      setInterval(() => {

        const onSend = (data) => {
          const buffer = Buffer.from(data, 'hex');
          console.log('send', buffer)
          client.send(buffer, 0, buffer.length, config.port, config.host, (err) => {
            if (err) {
              console.error("Error sending data:", err);
            } else {
              // console.log("Heartbeat sent successfully.");
            }
          });
        }

        onSend("A50401005501")
        // onSend("A50401005601")
        // 停止
        // onSend("A504010060F6")

      }, heartbeatInterval);
    });
  };

  client.on('message', (message, remote) => {
    console.log('message', message)
    // console.log(`Received ${message.length} bytes from ${remote.address}:${remote.port}`);
    parsePacket(message);
  });

  client.on('listening', () => {
    const address = client.address();
    console.log(`UDP client listening on ${address.address}:${address.port}`);
  });

  client.on('error', (err) => {
    console.error("Error occurred:", err);
    retryContent()
    client.close();
  });

  function parsePacket(packetData) {
    // 检查数据包是否以 0xA5 开头
    if (packetData[0] !== 0xA5) {
      // console.error('数据包格式错误，包头应为 0xA5');
      return;
    }

    // 提取数据包长度
    let len = packetData[1];

    // 提取 485 地址码
    let address = (packetData[2] << 8) | packetData[3];

    // 提取指令码
    let cmd = packetData[4];

    // 提取数据部分（如果有）
    let data = packetData.slice(5, 5 + len - 4);

    // 计算校验和
    let calculatedCK = calculateCK(packetData.slice(0, -1));
    let receivedCK = packetData[packetData.length - 1];

    // 检查校验和是否匹配
    if (calculatedCK !== receivedCK) {
      // console.error('校验和错误');
      return;
    }



    const antennaNumber = packetData[7];

    // console.log("antennaNumber", antennaNumber);

    // 输出解析结果
    // console.log('包头:', packetData[0]);
    // console.log('数据包长度:', len);
    // console.log('485 地址码:', address);
    // console.log('指令码:', cmd);
    // console.log('数据:', data);
    // console.log('校验和:', receivedCK);`


    const epcIndex = 5
    const epcEndIndex = len - epcIndex - 3
    const epc_data = data.slice(epcIndex, epcEndIndex);
    const rfid = epc_data.toString('hex').toUpperCase()
    // console.log('rfid', rfid);

    const key = `${config.host}-${antennaNumber}`;
    const sendResult = {
      key,
      ip: config.host,
      port: config.port,
      antenna: antennaNumber,
      rfid: rfid,
    };

    // if (antennaNumber !== 1) return

    on_set_rfid_judgment(sendResult)

    // data 转化为16进制大写字符串
    // console.log('数据:', data.toString('hex').toUpperCase());
  }

  function calculateCK(buffer) {
    let sum = 0;
    for (let i = 0; i < buffer.length; i++) {
      sum += buffer[i];
    }
    return (~sum + 1) & 0xFF;
  }

  function getEPCLengthFromPC(pcValue) {
    // 根据 6.1 节的规则映射 PC 值到 EPC 数据长度

    if (pcValue >= 0x0000 && pcValue <= 0x0700) {
      return 0;
    } else if (pcValue >= 0x0800 && pcValue <= 0x0F00) {
      return 2;
    } else if (pcValue >= 0x2800 && pcValue <= 0x2F00) {
      return 10;
    } else if (pcValue >= 0x3000 && pcValue <= 0x3700) {
      return 12;
    } else if (pcValue >= 0x3800 && pcValue <= 0x3F00) {
      return 14;
    } else if (pcValue >= 0x4000 && pcValue <= 0x4700) {
      return 16;
    } else if (pcValue >= 0xF800 && pcValue <= 0xFF00) {
      return 62;
    } else {
      console.error('未知的 PC 值，无法确定 EPC 数据长度');
      return -1;
    }
  }


  function retryContent() {
    setTimeout(onContentClient, 1000);
  }

  onContentClient();
};

connectUdp({
  host: "192.168.100.32",
  port: 4001,
});

// 添加一个监听器以优雅地处理程序退出，清除定时器
process.on("SIGINT", function () {
  console.log("\nGracefully shutting down from SIGINT (Ctrl-C)");
  process.exit();
});
